#include "RoomManager.hpp"
#include <fstream>
using namespace std;

void RoomManager::AddRoom(const BaseRoom& baseRoom)
{
	m_BaseRooms.push_back(baseRoom);
}

void RoomManager::AddPath(const BasePath& basePath, bool activePath)
{
	if(activePath)
		m_ActiveBasePaths.push_back(basePath);
	else
		m_NotActiveBasePaths.push_back(basePath);
}

// Gets a path from the list of active base paths
BasePath RoomManager::GetPath(int roomID)
{
	// iterate through all of the rooms.  If we have an ID math then return that room, otherwise return a default BasePath
	list<BasePath>::const_iterator it;
	for(it = m_ActiveBasePaths.begin(); it != m_ActiveBasePaths.end(); ++it)
	{
		if(it->ID_a == roomID || it->ID_b == roomID)
			return *it;
	}
	return BasePath();

}

void RoomManager::MergePathLists()
{
	list<BasePath>::iterator it;
	for(it = m_NotActiveBasePaths.begin(); it != m_NotActiveBasePaths.end(); ++it)
		m_ActiveBasePaths.push_back(*it);

	m_NotActiveBasePaths.clear();
}

void RoomManager::RemoveRoom(const Room& room)
{	
	if(m_Rooms.empty() || m_BaseRooms.empty())
		return;

	// iterate all rooms and check their IDs
	{
		bool found = false;
		list<Room>::iterator it, remove;
		for(it = m_Rooms.begin(); it != m_Rooms.end(); ++it)
		{
			// if the room we want to remove has the same ID as this room, then remove it
			if(room.ID == (it)->ID)
			{
				remove = it;
				found = true;
			}
		}
		if(found)
			m_Rooms.remove(*remove);
	}
	// do the same thing with base rooms
	{
		bool found = false;
		list<BaseRoom>::iterator it, remove;
		for(it = m_BaseRooms.begin(); it != m_BaseRooms.end(); ++it)
		{
			// if the room we want to remove has the same ID as this room, then remove it
			if(room.ID == (it)->ID)
			{
				remove = it;
				found = true;
			}
		}
		if(found)
			m_BaseRooms.remove(*remove);
	}

	// do the same thing with active base paths
	{
		bool found = false;
		list<BasePath>::iterator it, remove;
		for(it = m_ActiveBasePaths.begin(); it != m_ActiveBasePaths.end(); ++it)
		{
			// if the room we want to remove has the same ID as this room, then remove it
			if(room.ID == (it)->roomID)
			{
				remove = it;
				found = true;
			}
		}
		if(found)
			m_ActiveBasePaths.remove(*remove);
	}

	// do the same thing with not active base paths
	{
		bool found = false;
		list<BasePath>::iterator it, remove;
		for(it = m_NotActiveBasePaths.begin(); it != m_NotActiveBasePaths.end(); ++it)
		{
			// if the room we want to remove has the same ID as this room, then remove it
			if(room.ID == (it)->roomID)
			{
				remove = it;
				found = true;
			}
		}
		if(found)
			m_NotActiveBasePaths.remove(*remove);
	}

}

void RoomManager::AddRoom(const Room& room)
{
	m_Rooms.push_back(room);
}

void RoomManager::ExportToLua(string filename)
{
	ofstream file;
	file.open(filename.c_str());

	if(file.is_open())
	{
		list<BaseRoom>::const_iterator it = m_BaseRooms.begin();
		file << "do\n";
		file << "RegisterMap(CreateMap(" << it->imgID << ", " << it->x2.max << ", " << it->y2.max << "))\n\n";
		++it;
		
		for(it; it != m_BaseRooms.end(); ++it)
		{
			file << "AddRoom(" << it->x1.max << ", " << it->x1.min << ", " << it->y1.max << ", " << it->y1.min << ", " << 
				it->x2.max << ", " << it->x2.min << ", " << it->y2.max << ", " << it->y2.min << ", " << it->density << ", "
				<< it->imgID << ", " << it->algorithm << ")\n\n";
		}

		file << "SaveMap(\"Maps//Editor.map\")\n";
		file << "end\n";
	}
}

bool inBounds(const Vector2D& pos, const SDL_Rect& obj)
{
	if((pos.x > obj.x) && (pos.x < obj.x + obj.w) && (pos.y > obj.y) && (pos.y < obj.y + obj.h))
		return true;

	return false;
}

bool InRoom(const Vector2D& mos, const Room& room)
{
	SDL_Rect a;
	a.x = room.x1 * TILE_DIMENSIONS;
	a.y = room.y1 * TILE_DIMENSIONS;
	a.w = room.w * TILE_DIMENSIONS;
	a.h = room.h * TILE_DIMENSIONS;
	return inBounds(mos, a);
}

// Gets a list of rooms that are on screen
vector<Room*> RoomManager::GetRoomsOnscreen(ClippingPlane *pClippingPlane)
{
	vector<Room*> rtn;
	list<Room>::iterator it;
	SDL_Rect obj;

	SDL_Rect c;
	c.x = pClippingPlane->GetX() / 32.0,
		c.y = pClippingPlane->GetY() / 32.0,
		c.w = pClippingPlane->GetWidth(),
		c.h = pClippingPlane->GetHeight();

	for(it = m_Rooms.begin(); it != m_Rooms.end(); ++it)
	{
		obj.x = (it)->x1;
		obj.y = (it)->y1;
		obj.w = (it)->w;
		obj.h = (it)->h;

		
		if(inBounds(Vector2D(obj.x, obj.y), c) || inBounds(Vector2D(obj.x + obj.w, obj.y), c) || 
			inBounds(Vector2D(obj.x, obj.y + obj.h), c) || inBounds(Vector2D(obj.x + obj.w, obj.y + obj.h), c) || 
			inBounds(Vector2D(c.x + c.w / 2, c.y + c.h / 2), obj))

			rtn.push_back(&(*it));
		
	}

	return rtn;
}